home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / portage / bin / etc-update < prev    next >
Encoding:
Text File  |  2006-06-30  |  10.7 KB  |  419 lines

  1. #!/bin/bash
  2. # Copyright 1999-2006 Gentoo Foundation
  3. # Distributed under the terms of the GNU General Public License v2
  4. # $Id: etc-update 2221 2005-11-01 01:32:07Z vapier $
  5.  
  6. # Author Brandon Low <lostlogic@gentoo.org>
  7. #
  8. # Previous version (from which I've borrowed a few bits) by:
  9. # Jochem Kossen <j.kossen@home.nl>
  10. # Leo Lipelis <aeoo@gentoo.org>
  11. # Karl Trygve Kalleberg <karltk@gentoo.org>
  12.  
  13. export PORTAGE_CALLER="etc-update"
  14.  
  15. if type -p gsed >/dev/null ; then
  16.     function sed() { gsed "$@"; }
  17. fi
  18.  
  19. function get_config() {
  20.     item=$1
  21.  
  22.     # First strip off comment lines, then grab the configuration
  23.     # item. If there's more than one of the same configuration item,
  24.     # then allow the last setting to take precedence.
  25.     cut -d'#' -f1-1 /etc/etc-update.conf | \
  26.         sed -ne "s/^ *$item *= *\([\"']\{0,1\}\)\(.*\)\1/\2/p" |sed -e '$p;d'
  27. }
  28.  
  29. function scan() {
  30.  
  31.     echo "Scanning Configuration files..."
  32.     rm -rf ${TMP}/files > /dev/null 2>&1
  33.     mkdir ${TMP}/files || die "Failed mkdir command!" 1
  34.     count=0
  35.     input=0
  36.     
  37.     # Sanity check to make sure diff exists and works
  38.     if ! diff -v &>/dev/null ; then
  39.         echo "ERROR: 'diff' does not seem to work, aborting"
  40.         exit 1
  41.     fi
  42.  
  43.     for path in ${CONFIG_PROTECT} ; do
  44.         [ ! -d ${path} ] && continue
  45.  
  46.         ofile=""
  47.         for file in $(find ${path}/ -iname '._cfg????_*' ! -name '.*~' ! -name '.*.bak' |
  48.                sed -e "s:\(^.*/\)\(\._cfg[0-9]*_\)\(.*$\):\1\2\3\%\2\%\3:" |
  49.                sort -t'%' -k3 -k2 | LANG=POSIX LC_ALL=POSIX cut -f1 -d'%'); do
  50.             rpath=$(echo "${file/\/\///}" | sed -e "s:/[^/]*$::")
  51.             rfile=$(echo "${file/\/\///}" | sed -e "s:^.*/::")
  52.             for mpath in ${CONFIG_PROTECT_MASK}; do
  53.                 if [[ "${rpath}" == "${mpath}"* ]]; then
  54.                     mv ${rpath}/${rfile} ${rpath}/${rfile:10}
  55.                     break
  56.                 fi
  57.             done
  58.             [ ! -f ${file} ] && continue
  59.  
  60.  
  61.             if [[ "${ofile:10}" != "${rfile:10}" ]] || 
  62.                [[ ${opath} != ${rpath} ]]; then
  63.                 MATCHES=0
  64.                 if [[ "${EU_AUTOMERGE}" == "yes" ]]; then
  65.                     if [ ! -e "${rpath}/${rfile}" ] || [ ! -e "${rpath}/${rfile:10}" ]; then
  66.                         MATCHES=0
  67.                     else
  68.                         diff -Bbua ${rpath}/${rfile} ${rpath}/${rfile:10} | egrep '^[+-]' | egrep -v '^[+-][\t ]*#|^--- |^\+\+\+ ' | egrep -qv '^[-+][\t ]*$'
  69.                         MATCHES=$?
  70.                     fi
  71.                 elif [[ -z $(diff -Nua ${rpath}/${rfile} ${rpath}/${rfile:10}|
  72.                               grep "^[+-][^+-]"|grep -v '# .Header:.*') ]]; then
  73.                     MATCHES=1
  74.                 fi
  75.                 if [[ "${MATCHES}" == "1" ]]; then
  76.                     echo "Automerging trivial changes in: ${rfile:10}"
  77.                     mv ${rpath}/${rfile} ${rpath}/${rfile:10}
  78.                     continue
  79.                 else
  80.                     count=${count}+1
  81.                     echo "${rpath}/${rfile:10}" > ${TMP}/files/${count}
  82.                     echo "${rpath}/${rfile}" >> ${TMP}/files/${count}
  83.                     ofile="${rfile}"
  84.                     opath="${rpath}"
  85.                     continue
  86.                 fi
  87.             fi
  88.  
  89.             if [[ -z $(diff -Nua ${rpath}/${rfile} ${rpath}/${ofile}|
  90.                       grep "^[+-][^+-]"|grep -v '# .Header:.*') ]]; then
  91.                 mv ${rpath}/${rfile} ${rpath}/${ofile}
  92.                 continue
  93.             else
  94.                 echo "${rpath}/${rfile}" >> ${TMP}/files/${count}
  95.                 ofile="${rfile}"
  96.                 opath="${rpath}"
  97.             fi
  98.         done
  99.     done
  100.  
  101. }
  102.  
  103. function sel_file() {
  104.     local -i isfirst=0
  105.     until [[ -f ${TMP}/files/${input} ]] || \
  106.           [[ ${input} == -1 ]] || \
  107.           [[ ${input} == -3 ]]
  108.     do
  109.         local numfiles=$(ls ${TMP}/files|wc -l)
  110.         local numwidth=${#numfiles}
  111.         for file in $(ls ${TMP}/files|sort -n); do
  112.             if [[ ${isfirst} == 0 ]] ; then
  113.                 isfirst=${file}
  114.             fi
  115.             numshow=$(printf "%${numwidth}i${PAR} " ${file})
  116.             numupdates=$(( $(wc -l <${TMP}/files/${file}) - 1 ))
  117.             echo -n "${numshow}"
  118.             if [[ ${mode} == 0 ]] ; then
  119.                 echo "$(head -n1 ${TMP}/files/${file}) (${numupdates})"
  120.             else
  121.                 head -n1 ${TMP}/files/${file}
  122.             fi
  123.         done > ${TMP}/menuitems
  124.  
  125.         if [ "${OVERWRITE_ALL}" == "yes" ]; then
  126.             input=0
  127.         else
  128.             if [[ ${mode} == 0 ]] ; then
  129.                 echo "The following is the list of files which need updating, each 
  130. configuration file is followed by a list of possible replacement files."
  131.             else
  132.                 local my_title="Please select a file to update"
  133.             fi
  134.  
  135.             if [[ ${mode} == 0 ]] ; then
  136.                 cat ${TMP}/menuitems
  137.                 echo    "Please select a file to edit by entering the corresponding number."
  138.                 echo    "              (don't use -3 or -5 if you're unsure what to do)"
  139.                 echo    "              (-1 to exit) (-3 to auto merge all remaining files)"
  140.                 echo -n "                           (-5 to auto-merge AND not use 'mv -i'): "
  141.                 read input
  142.             else
  143.                 dialog --title "${title}" --menu "${my_title}" \
  144.                     0 0 0 $(echo -e "-1 Exit\n$(<${TMP}/menuitems)") \
  145.                     2> ${TMP}/input || die "User termination!" 0
  146.                 input=$(<${TMP}/input)
  147.             fi
  148.             if [[ ${input} == -5 ]] ; then
  149.                 input=-3
  150.                 export mv_opts=""
  151.             fi
  152.             if [[ ${input} == -3 ]] ; then
  153.                 input=0
  154.                 export OVERWRITE_ALL="yes"
  155.             fi
  156.         fi # -3 automerge
  157.         if [[ -z ${input} ]] || [[ ${input} == 0 ]] ; then
  158.             input=${isfirst}
  159.         fi
  160.     done
  161. }
  162.  
  163. function do_file() {
  164.     echo
  165.     local -i my_input
  166.     local -i fcount=0
  167.     until (( $(wc -l < ${TMP}/files/${input}) < 2 )); do
  168.         my_input=0
  169.         if (( $(wc -l < ${TMP}/files/${input}) == 2 )); then
  170.             my_input=1
  171.         fi
  172.         until (( ${my_input} > 0 )) && (( ${my_input} < $(wc -l < ${TMP}/files/${input}) )); do
  173.             fcount=0
  174.  
  175.             if [ "${OVERWRITE_ALL}" == "yes" ]; then
  176.                 my_input=0
  177.             else
  178.                 for line in $(<${TMP}/files/${input}); do
  179.                     if (( ${fcount} > 0 )); then
  180.                         echo -n "${fcount}${PAR} "
  181.                         echo "${line}"
  182.                     else
  183.                         if [[ ${mode} == 0 ]] ; then
  184.                             echo "Below are the new config files for ${line}:"
  185.                         else
  186.                             local my_title="Please select a file to process for ${line}"
  187.                         fi
  188.                     fi
  189.                     fcount=${fcount}+1
  190.                 done > ${TMP}/menuitems
  191.  
  192.                 if [[ ${mode} == 0 ]] ; then
  193.                     cat ${TMP}/menuitems
  194.                     echo -n "Please select a file to process (-1 to exit this file): "
  195.                     read my_input
  196.                 else
  197.                     dialog --title "${title}" --menu "${my_title}" \
  198.                         0 0 0 $(echo -e "$(<${TMP}/menuitems)\n${fcount} Exit") \
  199.                         2> ${TMP}/input || die "User termination!" 0
  200.                     my_input=$(<${TMP}/input)
  201.                 fi
  202.             fi # OVERWRITE_ALL
  203.  
  204.             if [[ ${my_input} == 0 ]] ; then
  205.                 my_input=1
  206.             elif [[ ${my_input} == -1 ]] ; then
  207.                 input=0 
  208.                 return
  209.             elif [[ ${my_input} == ${fcount} ]] ; then
  210.                 break
  211.             fi
  212.         done
  213.         if [[ ${my_input} == ${fcount} ]] ; then
  214.             break
  215.         fi
  216.  
  217.         fcount=${my_input}+1
  218.  
  219.         file=$(sed -e "${fcount}p;d" ${TMP}/files/${input})
  220.         ofile=$(head -n1 ${TMP}/files/${input})
  221.  
  222.         do_cfg "${file}" "${ofile}"
  223.  
  224.         sed -e "${fcount}!p;d" ${TMP}/files/${input} > ${TMP}/files/sed
  225.         mv ${TMP}/files/sed ${TMP}/files/${input}
  226.  
  227.         if [[ ${my_input} == -1 ]] ; then
  228.             break
  229.         fi
  230.     done
  231.     echo
  232.     rm ${TMP}/files/${input}
  233.     count=${count}-1
  234. }
  235.  
  236. function do_cfg() {
  237.     
  238.     local file="${1}"
  239.     local ofile="${2}"
  240.     local -i my_input=0
  241.     
  242.     until (( ${my_input} == -1 )) || [ ! -f ${file} ]; do
  243.         if [ "${OVERWRITE_ALL}" == "yes" ]; then
  244.             my_input=1
  245.         else
  246.           showdiffcmd=$(echo "${diff_command}" |
  247.                 sed -e "s:%file1:${ofile}:" -e "s:%file2:${file}:")
  248.                 
  249.             if [ "${using_editor}" == 0 ]; then
  250.                 (
  251.                     echo "Showing differences between ${ofile} and ${file}"
  252.                     ${showdiffcmd}
  253.                 ) | ${pager}
  254.             else
  255.                 echo "Beginning of differences between ${ofile} and ${file}"
  256.                 ${showdiffcmd}
  257.                 echo "End of differences between ${ofile} and ${file}"
  258.             fi
  259.             if [ -L "${file}" ]; then
  260.                 echo
  261.                 echo "-------------------------------------------------------------"
  262.                 echo "NOTE: File is a symlink to another file. REPLACE recommended."
  263.                 echo "      The original file may simply have moved. Please review."
  264.                 echo "-------------------------------------------------------------"
  265.                 echo
  266.             fi
  267.             echo -n "1) Replace original with update
  268. 2) Delete update, keeping original as is
  269. 3) Interactively merge original with update
  270. 4) Show differences again
  271. Please select from the menu above (-1 to ignore this update): "
  272.             read my_input
  273.         fi
  274.         
  275.         case ${my_input} in
  276.             1) echo "Replacing ${ofile} with ${file}"
  277.                mv ${mv_opts} ${file} ${ofile}
  278.                my_input=-1
  279.                continue
  280.                ;;
  281.             2) echo "Deleting ${file}"
  282.                rm ${rm_opts} ${file}
  283.                continue
  284.                ;;
  285.             3) do_merge "${file}" "${ofile}"
  286.                my_input=${?}
  287. #               [ ${my_input} == 255 ] && my_input=-1
  288.                continue
  289.                ;;
  290.             4) continue
  291.                ;;
  292.             *) continue
  293.                ;;
  294.         esac
  295.     done
  296. }
  297.  
  298. function do_merge() {
  299.     
  300.     local file="${1}"
  301.     local ofile="${2}"
  302.     local mfile="${2}.merged"
  303.     local -i my_input=0
  304.     echo "${file} ${ofile} ${mfile}"
  305.  
  306.     if [ -e ${mfile} ] ; then
  307.         echo "A previous version of the merged file exists, cleaning..."
  308.         rm ${rm_opts} ${mfile}
  309.     fi
  310.  
  311.     until (( ${my_input} == -1 )); do
  312.         echo "Merging ${file} and ${ofile}"
  313.         $(echo "${merge_command}" |
  314.          sed -e "s:%merged:${mfile}:g" \
  315.               -e "s:%orig:${ofile}:g" \
  316.              -e "s:%new:${file}:g")
  317.         until (( ${my_input} == -1 )); do    
  318.             echo -n "1) Replace ${ofile} with merged file
  319. 2) Show differences between merged file and original
  320. 3) Remerge original with update
  321. 4) Edit merged file
  322. 5) Return to the previous menu
  323. Please select from the menu above (-1 to exit, losing this merge): "
  324.             read my_input
  325.             case ${my_input} in
  326.                 1) echo "Replacing ${ofile} with ${mfile}"
  327.                    chmod --reference=${ofile} ${mfile}
  328.                    mv ${mv_opts} ${mfile} ${ofile}
  329.                    rm ${rm_opts} ${file}
  330.                    return 255
  331.                    ;;
  332.                 2) ( echo "Showing differences between ${ofile} and ${mfile}"
  333.                      $(echo "${diff_command}" | \
  334.                       sed -e "s:%file1:${ofile}:" \
  335.                             -e "s:%file2:${mfile}:") ) | ${pager}
  336.                    continue
  337.                    ;;
  338.                 3) break
  339.                    ;;
  340.                 4) ${EDITOR:-nano -w} "${mfile}"
  341.                    continue
  342.                      ;;
  343.                 5) rm ${rm_opts} ${mfile}
  344.                    return 0
  345.                    ;;
  346.                 *) continue
  347.                    ;;
  348.             esac
  349.         done
  350.     done
  351.     rm ${rm_opts} ${mfile}
  352.     return 255
  353. }
  354.  
  355. function die() {
  356.     trap "" TERM
  357.     trap "" KILL
  358.     echo "Exiting: ${1}"
  359.     rm -rf ${TMP}
  360.     exit ${2}
  361. }
  362.  
  363. #
  364. # Run the script
  365. #
  366. scriptname=$(basename $0)
  367.  
  368. trap die term
  369.  
  370. export PORTAGE_TMPDIR=$(/usr/lib/portage/bin/portageq envvar PORTAGE_TMPDIR)
  371.  
  372. TMP="${PORTAGE_TMPDIR}/$$"
  373. rm -rf ${TMP} 2> /dev/null
  374. mkdir ${TMP} || die "failed mkdir command!" 1
  375.  
  376. # I need the CONFIG_PROTECT value
  377. CONFIG_PROTECT=$(/usr/lib/portage/bin/portageq envvar CONFIG_PROTECT)
  378. CONFIG_PROTECT_MASK=$(/usr/lib/portage/bin/portageq envvar CONFIG_PROTECT_MASK)
  379.  
  380. # load etc-config's configuration
  381. EU_AUTOMERGE=$(get_config eu_automerge)
  382. rm_opts=$(get_config rm_opts)
  383. mv_opts=$(get_config mv_opts)
  384. cp_opts=$(get_config cp_opts)
  385. pager=$(get_config pager)
  386. diff_command=$(get_config diff_command)
  387. using_editor=$(get_config using_editor)
  388. merge_command=$(get_config merge_command)
  389. declare -i mode=$(get_config mode)
  390. [ -z ${mode} ] && mode=0
  391. [ -z "${pager}" ] && pager="cat"
  392.  
  393. #echo "rm_opts: $rm_opts, mv_opts: $mv_opts, cp_opts: $cp_opts"
  394. #echo "pager: $pager, diff_command: $diff_command, merge_command: $merge_command" 
  395.  
  396. if (( ${mode} == 0 )); then
  397.     PAR=")"
  398. else
  399.     PAR=""
  400. fi
  401.  
  402. declare -i count=0
  403. declare input=0
  404. declare title="Gentoolkit's etc-update tool!"
  405.  
  406. scan
  407.  
  408. until (( ${input} == -1 )); do
  409.     if (( ${count} == 0 )); then
  410.         die "Nothing left to do; exiting. :)" 0
  411.     fi
  412.     sel_file
  413.     if (( ${input} != -1 )); then
  414.         do_file
  415.     fi
  416. done
  417.  
  418. die "User termination!" 0
  419.